package com.quotes.indicators;

import java.util.Date;

import com.quotes.*;
import com.quotes.datamodell.*;

public class RsiIndicator
{
	private Quotes quotes = null;
	private TimeSeries closePrices = null;
	private TimeSeries rsi = null;
	
	public RsiIndicator(Quotes quotes, int ticks) {
		this.quotes = quotes;
		closePrices = quotes.getQuote(QuotesType.CLOSE);
		rsi = calculateRSI(closePrices, ticks);
	}
	
	public TimeSeries getRsi() {
		return rsi;
	}
	
	public boolean isHigherOrEqual(Date date, double boundary) {
		double value = rsi.getOr0(date);
		return (value >= boundary);
	}
	
	public boolean isLower(Date date, double boundary) {
		double value = rsi.getOr0(date);
		return (value < boundary);
	}
	
	public boolean isBetween(Date date, double lower, double upper) {
		double value = rsi.getOr0(date);
		return (value > lower && value < upper);
	}
	
	public static TimeSeries calculateRSI(TimeSeries input, int ticks) {
		TimeSeries result = new TimeSeries();
		double[] data = input.ValuesAsArray();
		Date[] keys = input.DatesAsArray();
		
		for (int i=ticks; i<data.length; i++) {
			double avgUp = sumDirections(data, i, ticks, true) / ticks;
			double avgDown = sumDirections(data, i, ticks, false) / ticks;
			double rsi = 100 - (100 / (1 + (avgUp / avgDown)));
			result.put(keys[i], rsi);
		}
		
		return result;
	}
	
	private static double sumDirections(double[] data, int index, int count, boolean isUpwards) {
		if (index == 0 || count == 0)
			return 0;
		
		double value = data[index] - data[index - 1];
		
		if (isUpwards)
			value = Math.max(0, value);
		else
			value = Math.max(0, -value);

		value = value + sumDirections(data, index - 1, count - 1, isUpwards);
		
		return value;
	}
}
